package com.yilin.commons.util;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.Hashtable;
import java.util.Iterator;

/**
 * 生成朋友圈分享图相关接口
 * 用于测试，不用太过于关注代码规范
 *
 * @author zhangkeke
 * @since 2017/10/18 15:31
 */
public class SharedImageUtils {
    /* 要放置的二维码大小 */
    private static final int QRCODE_SIZE = 300;
    /* 要放置的二维码高度 */
    private static final int QRCODE_Y = 540;
    /* 要放置的头像半径 */
    public static final int AVATAR_SIZE = 160;
    /* 要放置的头像y坐标 */
    private static final int AVATAR_Y = 150;
    /* 昵称的高度 */
    private static final int FONT_Y = 370;
    /* 推广文案的高度 */
    private static final int COPYWRITER = 415;
    /* 二维码识别图案高度 */
    private static final int RECOGNITION_QRCODE_Y = 890;
    /* 二维码识别图案大小 */
    private static final int RECOGNITION_QRCODE_SIZE = 260;
    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;
    private static final int margin = 0;
    private static final int LogoPart = 4;

    //-------------------------------------------------------------------------
    private static final int TEXT_LEFT = 10;
    private static final int TEXT_TOP = 30;

    /**
     * 裁剪图片
     *
     * @param img          the img
     * @param originWidth  the origin width
     * @param originHeight the origin height
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage cutPicture(BufferedImage img, int originWidth, int originHeight) throws IOException {
        int width = img.getWidth();  // 原图的宽度
        int height = img.getHeight();  //原图的高度

        int newImage_x = 0; // 要截图的坐标
        int newImage_y = 0; // 要截图的坐标
        if (width > originWidth) {
            newImage_x = (width - originWidth) / 2;
        }
        if (height > originHeight) {
            newImage_y = height - originHeight;
        }
        return cutJPG(img, newImage_x, newImage_y, originWidth, originHeight);
    }

    /**
     * 图片拉伸
     *
     * @param originalImage the original image
     * @param originWidth   the origin width
     * @param originHeight  the origin height
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage zoomPicture(String originalImage, int originWidth, int originHeight) throws Exception {
        // 原来的图片
        BufferedImage img = ImageIO.read(new File(originalImage));

        int width = img.getWidth();  // 原图的宽度
        int height = img.getHeight();  //原图的高度

        int scaledWidth = width;
        int scaledHeight = height;
        // 如果不是正方形
        if (width == height) {
            // 按照originHeight进行缩放
            scaledWidth = originHeight;
            scaledHeight = originHeight;
        } else {
            if (width > height) {
                // 按照originHeight进行缩放
                scaledWidth = (scaledWidth * originHeight) / scaledHeight;
                scaledHeight = originHeight;
            } else {
                // 宽高比例
                int originPercent = (originHeight * 100) / originWidth;
                int newPercent = (height * 100) / width;
                if (newPercent >= originPercent) {
                    // 按照originWidth进行缩放
                    scaledWidth = originWidth;
                    scaledHeight = (originHeight * scaledWidth) / scaledWidth;
                } else {
                    // 按照originHeight进行缩放
                    scaledWidth = (scaledWidth * originHeight) / scaledHeight;
                    scaledHeight = originHeight;
                }
            }
        }
        Image schedImage = img.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
        // 新的图片
        BufferedImage bufferedImage = new BufferedImage(scaledWidth, scaledHeight, img.getType());
        Graphics2D g = bufferedImage.createGraphics();
        // 绘制
        g.drawImage(schedImage, 0, 0, null);
        g.dispose();
        return bufferedImage;
    }

    /**
     * 进行裁剪操作
     *
     * @param originalImage the original image
     * @param x             the x
     * @param y             the y
     * @param width         the width
     * @param height        the height
     * @return the buffered image
     * @throws IOException the io exception
     */
    public static BufferedImage cutJPG(BufferedImage originalImage, int x, int y, int width, int height) throws IOException {
        Iterator<ImageReader> iterator = ImageIO.getImageReadersByFormatName("jpg");
        ImageReader reader = iterator.next();
        // 转换成字节流
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(originalImage, "jpg", outputStream);
        InputStream is = new ByteArrayInputStream(outputStream.toByteArray());

        ImageInputStream iis = ImageIO.createImageInputStream(is);
        reader.setInput(iis, true);
        ImageReadParam param = reader.getDefaultReadParam();
        Rectangle rect = new Rectangle(x, y, width, height);
        param.setSourceRegion(rect);
        BufferedImage bi = reader.read(0, param);
        return bi;
    }

    /**
     * 合并头像和昵称
     *
     * @param baseImage the base image
     * @param topImage  the top image
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage mergePicture(BufferedImage baseImage, BufferedImage topImage, int left, int top, int imgW, int imgH) throws IOException {
        int width = baseImage.getWidth(null); //底图的宽度
        int height = baseImage.getHeight(null); //底图的高度
        // 按照底图的宽高生成新的图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.createGraphics();
        g.drawImage(baseImage, 0, 0, width, height, null);

        int smallWidth = topImage.getWidth(null);   // 上层图片的宽度
        // 设置上层图片放置的位置的坐标及大小
        g.drawImage(topImage, left, top, imgW, imgH, null);

        // 普通字体
        Font font = new Font("微软雅黑", Font.PLAIN, 30);
        g.setFont(font);
        g.setColor(new Color(68, 68, 68));


        return image;
    }


    /**
     * 按指定的字节数截取字符串（一个中文字符占3个字节，一个英文字符或数字占1个字节）
     *
     * @param sourceString 源字符串
     * @param cutBytes     要截取的字节数
     * @return
     */
    public static String cutString(String sourceString, int cutBytes) {
        if (sourceString == null || "".equals(sourceString.trim())) {
            return "";
        }
        int lastIndex = 0;
        boolean stopFlag = false;
        int totalBytes = 0;
        for (int i = 0; i < sourceString.length(); i++) {
            String s = Integer.toBinaryString(sourceString.charAt(i));
            if (s.length() > 8) {
                totalBytes += 3;
            } else {
                totalBytes += 1;
            }
            if (!stopFlag) {
                if (totalBytes == cutBytes) {
                    lastIndex = i;
                    stopFlag = true;
                } else if (totalBytes > cutBytes) {
                    lastIndex = i - 1;
                    stopFlag = true;
                }
            }
        }
        if (!stopFlag) {
            return sourceString;
        } else {
            return sourceString.substring(0, lastIndex + 1);
        }
    }

    /**
     * 合并二维码及二维码识别图
     *
     * @param baseImage   the base image
     * @param qrcodeImage the qrcode image
     * @return the buffered image
     * @throws IOException
     */
    public static BufferedImage mergeQrcode(BufferedImage baseImage, String qrcodeImage, int left, int top, int imgW, int imgH) throws IOException {
        BufferedImage qrcodeBufferImage = ImageIO.read(new File(qrcodeImage));
        return mergeQrcode(baseImage, qrcodeBufferImage, left, top, imgW, imgH, false);
    }

    public static BufferedImage mergeQrcode(BufferedImage baseImage, BufferedImage qrcodeImage, int left, int top, int imgW, int imgH) throws IOException {
        return mergeQrcode(baseImage, qrcodeImage, left, top, imgW, imgH, false);
    }

    public static BufferedImage mergeQrcode(BufferedImage baseImage, BufferedImage qrcodeImage, int left, int top, int imgW, int imgH, Boolean isCenter) throws IOException {
        int width = baseImage.getWidth(null); //底图的宽度
        int height = baseImage.getHeight(null); //底图的高度
        // 按照底图的宽高生成新的图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.createGraphics();
        g.drawImage(baseImage, 0, 0, width, height, null);
        // 设置上层图片放置的位置的坐标及大小，坐标居中
        if (isCenter) {
            g.drawImage(qrcodeImage, (width - imgW) / 2, top, imgW, imgH, null);
        } else {
            g.drawImage(qrcodeImage, left, top, imgW, imgH, null);
        }
        g.dispose();
        return image;
    }

    public static void main(String[] args) throws IOException {
        BufferedImage truckImg = SharedImageUtils.getBufferedImageByUrl("http://117.187.230.142:9000/truck/longDistanceCart_6m8/highHurdle/0.png");
    }

    /**
     * 图片上添加文字
     *
     * @param src        the src
     * @param copywriter the copywriter
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage drawTextInImage(BufferedImage src, String copywriter, int left, int top, Color color, int fontSize,String fontName) {
        return drawTextInImage(src, copywriter, left, top, color, fontSize, false, false, Font.PLAIN, fontName);
    }

    public static BufferedImage drawTextInImage(BufferedImage src, String copywriter, int left, int top, Color color, int fontSize, Integer fonWeight,String fontName) {
        return drawTextInImage(src, copywriter, left, top, color, fontSize, false, false, fonWeight,fontName);
    }

    public static BufferedImage drawTextInImage(BufferedImage src, String copywriter, int left, int top, Color color, int fontSize, Boolean isLevel, Boolean isVertical,String fontName) {
        return drawTextInImage(src, copywriter, left, top, color, fontSize, isLevel, isVertical, Font.PLAIN,fontName);
    }

    public static BufferedImage drawTextInImage(BufferedImage src, String copywriter, int left, int top, Color color, int fontSize, Boolean isLevel, Boolean isVertical, Integer fonWeight,String fontName) {
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        g.drawImage(src, 0, 0, width, height, null);
        // 长度和位置
        Font font = new Font(fontName, fonWeight, fontSize);
        g.setFont(font);
        FontMetrics fm = g.getFontMetrics(font);
        int textWidth = fm.stringWidth(copywriter);
        g.setColor(color);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 先按字节来换行，英文单词空格问题暂时未考虑
        if (textWidth > 60) {
            String firstLine = cutString(copywriter, 55);
            String secondLine = copywriter.substring(firstLine.length());
            if (secondLine.length() >= 40) {
                secondLine = copywriter.substring(firstLine.length(), firstLine.length() + 25);
            }
            if (isLevel && isVertical) {
                g.drawString(firstLine, (width - textWidth) / 2, (height - fontSize) / 2);
                g.drawString(secondLine, (width - textWidth) / 2 + fontSize, (height - fontSize) / 2 + fontSize);
            } else if (isLevel) {
                g.drawString(firstLine, (width - textWidth) / 2, TEXT_TOP + top);
                g.drawString(secondLine, (width - textWidth) / 2, TEXT_TOP + top + fontSize + fontSize);
            } else if (isVertical) {
                g.drawString(firstLine, TEXT_LEFT + left, (height - fontSize) / 2);
                g.drawString(secondLine, TEXT_LEFT + left + fontSize, (height - fontSize) / 2 + fontSize);
            } else {
                g.drawString(firstLine, TEXT_LEFT + left, TEXT_TOP + top);
                g.drawString(secondLine, TEXT_LEFT + left, TEXT_TOP + top + fontSize);
            }

        } else {
            if (isLevel && isVertical) {
                g.drawString(copywriter, (width - textWidth) / 2, (height - fontSize) / 2);
            } else if (isLevel) {
                g.drawString(copywriter, (width - textWidth) / 2, TEXT_TOP + top);
            } else if (isVertical) {
                g.drawString(copywriter, TEXT_LEFT + left, (height - fontSize) / 2);
            } else {
                g.drawString(copywriter, TEXT_LEFT + left, TEXT_TOP + top);

            }
        }
        g.dispose();

        return image;
    }

    /**
     * 方形转为圆形
     *
     * @param img    the img
     * @param radius the radius 半径
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage convertRoundedImage(BufferedImage img, int radius) {
        BufferedImage result = new BufferedImage(radius, radius, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = result.createGraphics();
        //在适当的位置画图
        g.drawImage(img, (radius - img.getWidth(null)) / 2, (radius - img.getHeight(null)) / 2, null);

        //圆角
        RoundRectangle2D round = new RoundRectangle2D.Double(0, 0, radius, radius, radius * 2, radius * 2);
        Area clear = new Area(new Rectangle(0, 0, radius, radius));
        clear.subtract(new Area(round));
        g.setComposite(AlphaComposite.Clear);

        //抗锯齿
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.fill(clear);
        g.dispose();

        return result;
    }

    /**
     * 图像等比例缩放
     *
     * @param img     the img
     * @param maxSize the max size
     * @param type    the type
     * @return the scaled image
     */
    private static BufferedImage getScaledImage(BufferedImage img, int maxSize, int type) {
        int w0 = img.getWidth();
        int h0 = img.getHeight();
        int w = w0;
        int h = h0;
        // 头像如果是长方形：
        // 1:高度与宽度的最大值为maxSize进行等比缩放,
        // 2:高度与宽度的最小值为maxSize进行等比缩放
        if (type == 1) {
            w = w0 > h0 ? maxSize : (maxSize * w0 / h0);
            h = w0 > h0 ? (maxSize * h0 / w0) : maxSize;
        } else if (type == 2) {
            w = w0 > h0 ? (maxSize * w0 / h0) : maxSize;
            h = w0 > h0 ? maxSize : (maxSize * h0 / w0);
        }
        Image schedImage = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
        BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bufferedImage.createGraphics();
        g.drawImage(schedImage, 0, 0, null);
        return bufferedImage;
    }

    /**
     * 对头像处理
     *
     * @param image  the image
     * @param radius the radius
     * @return the buffered image
     * @throws Exception the exception
     */
    public static BufferedImage createRoundedImage(String image, int radius) throws Exception {
        BufferedImage img = ImageIO.read(new File(image));
        // 1. 按原比例缩减
        BufferedImage fixedImg = getScaledImage(img, radius, 2);
        // 2. 居中裁剪
        fixedImg = cutPicture(fixedImg, radius, radius);
        // 3. 把正方形生成圆形
        BufferedImage bufferedImage = convertRoundedImage(fixedImg, radius);
        return bufferedImage;
    }


    /**
     * 生成二维码带logo
     *
     * @param content  内容
     * @param logoPath logo路径
     * @param width    图片宽度
     * @param height   图片高度
     */
    public static BufferedImage qrcodeLogo(String content, String logoPath, int width, int height) throws IOException {
        BitMatrix bitMatrix = setBitMatrix(content, width, height);
        BufferedImage image = toBufferedImage(bitMatrix);
        image = addLogo(image, logoPath);
        return image;
    }

    /**
     * 生成二维码矩阵信息
     *
     * @param content 二维码图片内容
     * @param width   二维码图片宽度
     * @param height  二维码图片高度
     */
    public static BitMatrix setBitMatrix(String content, int width, int height) {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
        hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小
        BitMatrix bitMatrix = null;
        try {
            bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return bitMatrix;
    }

    /**
     * 生成二维码图片
     *
     * @param matrix 二维码矩阵信息
     */
    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }

    /**
     * 在二维码图片中添加logo图片
     *
     * @param image    二维码图片
     * @param logoPath logo图片路径
     */
    public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException {
        Graphics2D g = image.createGraphics();
        BufferedImage logoImage = ImageIO.read(new File(logoPath));
        // 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
        int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
        int height = width;
        // 计算logo图片放置位置
        int x = (image.getWidth() - width) / 2;
        int y = (image.getHeight() - height) / 2;
        // 在二维码图片上绘制logo图片
        g.drawImage(logoImage, x, y, width, height, null);
        // 绘制logo边框,可选
//        g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10);
        g.setStroke(new BasicStroke(2)); // 画笔粗细
        g.setColor(Color.WHITE); // 边框颜色
        g.drawRect(x, y, width, height); // 矩形边框
        logoImage.flush();
        g.dispose();
        return image;
    }

    /*隐藏姓名*/
    public static String nameHide(String name) {
        if (name == null && name.length() < 2) return "*";
        if (name.length() == 2) return name.substring(0, 1) + "*";
        if (name.length() > 2) {
            StringBuilder syboo = new StringBuilder();
            for (int i = 0; i < name.length() - 2; i++) {
                syboo.append("*");
            }
            StringBuilder str = new StringBuilder();
            str.append(name, 0, 1);
            str.append(syboo);
            str.append(name.substring(name.length() - 1));
            return str.toString();
        }
        return null;
    }

    public static BufferedImage getBufferedImageByUrl(String url)  {
        try {
            return ImageIO.read(new URL(url));
        } catch (Exception e) {
            return null;
        }

    }



}